﻿using System;
using System.Data;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Threading;
using Microsoft.Win32;

namespace Script_Text_Editor_WPF_Edition
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        /// <summary>
        /// 文本解析库
        /// </summary>
        Library.LibraryLinker library = new Library.LibraryLinker();
        /// <summary>
        /// 工作目录
        /// </summary>
        string scriptsPath = Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath) + @"\Scripts";
        string newScriptsPath = Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath) + @"\NewScripts";
        string savedTranslationsPath = Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath) + @"\SavedTranslations";
        /// <summary>
        /// 内容更改指示
        /// </summary>
        bool isTextChanged = false;
        /// <summary>
        /// 文本列表
        /// </summary>
        public DataTable dataTable = new DataTable();
        /// <summary>
        /// 当前编辑的文本的路径
        /// </summary>
        string currentFilePath = string.Empty;
        /// <summary>
        /// 自动存档计时器
        /// </summary>
        public DispatcherTimer timer = new DispatcherTimer();

        //==========================================================================

        /// <summary>
        /// 使某条目为选定状态并移动到视野内
        /// </summary>
        /// <param name="index">条目号</param>
        public void SelectListViewItem(int index)
        {
            if (index < 0 || index > listViewMain.Items.Count - 1)
                return;

            listViewMain.SelectedItems.Clear();
            listViewMain.SelectedIndex = index;

            BringCurrentItemIntoView();
        }

        /// <summary>
        /// 移动当前选定项目至视野内，并保持当前项下的某几项也在视野内
        /// </summary>
        public void BringCurrentItemIntoView()
        {
            if (listViewMain.SelectedItem == null) return;

            int intToIndex = (listViewMain.SelectedIndex + 2 < listViewMain.Items.Count - 2) ? listViewMain.SelectedIndex + 2 : listViewMain.SelectedIndex;
            listViewMain.ScrollIntoView(listViewMain.Items[intToIndex]);
        }

        /// <summary>
        /// 获得当年选中项目中的文本框
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        private TextBox GetElement(int listViewIndex, string name)
        {
            ListViewItem lvi = (ListViewItem)listViewMain.ItemContainerGenerator.ContainerFromIndex(listViewIndex);

            TextBox textBox = null;
            if (lvi != null)
            {
                ContentPresenter templateParent = FrameworkSupport.GetFrameworkElementByName<ContentPresenter>(lvi);

                DataTemplate dataTemplate = listViewMain.ItemTemplate;

                if (dataTemplate != null && templateParent != null)
                    textBox = dataTemplate.FindName(name, templateParent) as TextBox;
            }
            return textBox;
        }

        private void BeginWorkWithFile(string path)
        {
            currentFilePath = path;

            using (BinaryReader br = new BinaryReader(new FileStream(path, FileMode.Open)))
            {
                string strLines = library.GetStringCollection(br.ReadBytes((int)br.BaseStream.Length));
                string[] lines = Regex.Split(strLines, library.GetStringBreakLineChar());

                br.Close();

                dataTable.Rows.Clear();

                foreach (string s in lines)
                {
                    string ss = s;
                    if (library.GetCanMakeNewLine())
                        ss = ss.Replace(library.GetNewLineBreakChar(), Environment.NewLine);

                    dataTable.Rows.Add(ss, ss, false);
                }

                if (listViewMain.Items.Count > 0)
                {
                    listViewMain.SelectedIndex = 0;
                    listViewMain.Focus();
                    //GetElement(listViewMain.SelectedIndex, "textBoxNew").Focus();
                }
            }

            //开启自动保存
            timer.IsEnabled = true;

            textBlockInfo.Text = Path.GetFileName(currentFilePath) + " 已载入。";
        }

        private void ContinueWorkWithFile(string path)
        {
            string[] strLines;

            using (StreamReader sr = new StreamReader(new FileStream(path, FileMode.Open), Encoding.UTF8))
            {
                strLines = sr.ReadToEnd().Replace(Environment.NewLine, "\n").Split('\n');
                sr.Close();
            }
            //Check file
            if (strLines.Length < 6)
            {
                MessageBox.Show("文件不正确，无法继续。");
                return;
            }
            if (!strLines[0].StartsWith("Script Text Editor"))
            {
                MessageBox.Show("文件不正确，无法继续。");
                return;
            }

            //Load org file
            BeginWorkWithFile(strLines[1]);
            //Begin import
            //Check file line
            if ((Int32.Parse(strLines[3]) != dataTable.Rows.Count) || ((strLines.Length - 3 - 6) / 3 != dataTable.Rows.Count))
            {
                MessageBox.Show("行数不等，无法继续。");
                return;
            }
            //Do Import
            int crtLine = 7;
            for (int i = 0; i < dataTable.Rows.Count; i++)
                dataTable.Rows[i]["NewText"] =
                    strLines[crtLine + 3 * i]
                    .Substring(7)
                    .Replace(library.GetNewLineBreakChar(), Environment.NewLine)
                    ;

            textBlockInfo.Text = Path.GetFileName(currentFilePath) + " 已载入。";
        }

        private void SaveWorkWithFile(string path)
        {
            using (StreamWriter sw = new StreamWriter(new FileStream(path, FileMode.Create), Encoding.UTF8))
            {
                sw.WriteLine("Script Text Editor Saved Translation - " + library.GetLibraryInfo());
                sw.WriteLine(currentFilePath);
                sw.WriteLine(listViewMain.SelectedIndex.ToString());
                sw.WriteLine(dataTable.Rows.Count);
                sw.WriteLine("==================BEGIN==================");
                sw.WriteLine();

                int i = 1;
                foreach (DataRow dr in dataTable.Rows)
                {
                    if (library.GetCanMakeNewLine())
                    {
                        sw.WriteLine(
                            string.Format(
                            "<{0}>{1}",
                            i.ToString().PadLeft(5, '0'),
                            ((string)dr["OrgText"]).Replace(Environment.NewLine, library.GetNewLineBreakChar())
                            ));
                        sw.WriteLine(
                            string.Format(
                            "<{0}>{1}",
                            i.ToString().PadLeft(5, '0'),
                            ((string)dr["NewText"]).Replace(Environment.NewLine, library.GetNewLineBreakChar())
                            ));
                    }
                    else
                    {
                        sw.WriteLine(string.Format("<{0}>{1}", i.ToString().PadLeft(5, '0'), dr["OrgText"]));
                        sw.WriteLine(string.Format("<{0}>{1}", i.ToString().PadLeft(5, '0'), dr["NewText"]));
                    }
                    sw.WriteLine();
                    i++;
                }

                sw.WriteLine();
                sw.WriteLine("==================END==================");

                sw.Close();
            }

            textBlockInfo.Text = Path.GetFileName(currentFilePath) + " 已保存。";
            isTextChanged = false;
        }

        private void FinishWorkWithFile(string path)
        {
            string newFile = string.Empty;

            foreach (DataRow row in dataTable.Rows)
            {
                string ss = row.ItemArray[1].ToString();
                if (library.GetCanMakeNewLine())
                    ss = ss.Replace(Environment.NewLine, library.GetNewLineBreakChar());

                newFile += ss + library.GetStringBreakLineChar();
            }

            newFile = newFile.Substring(0, newFile.Length - Environment.NewLine.Length);

            using (BinaryWriter bw = new BinaryWriter(new FileStream(path, FileMode.Create)))
            {
                bw.Write(library.SetStringCollection(newFile));

                bw.Close();
            }

            textBlockInfo.Text = Path.GetFileName(currentFilePath) + " 已保存。";
            isTextChanged = false;
        }

        /// <summary>
        /// 查找指定的关键字
        /// </summary>
        /// <param name="str">目标字符串</param>
        /// <param name="startIndex">起始位置</param>
        /// <param name="step">方向</param>
        /// <param name="mode">查找方式：0-原文及译文1-原文2-译文</param>
        /// <returns>目标的编号，若没有找到则返回 -1</returns>
        private int FindTextInDataTable(string str, int startIndex, int step, int mode)
        {
            if (dataTable.Rows.Count == 0)
                return -1;

            for (int i = startIndex; i < dataTable.Rows.Count; i += step)
            {
                if (i < 0)
                    return -1;

                if (mode == 0 || mode == 1)//原文
                    if (((string)dataTable.Rows[i]["OrgText"]).Contains(str))
                        return i;
                if (mode == 0 || mode == 2)//译文
                    if (((string)dataTable.Rows[i]["NewText"]).Contains(str))
                        return i;
            }
            return -1;
        }

        //==========================================================================

        public MainWindow()
        {
            InitializeComponent();

            //计时器
            timer.Interval = new TimeSpan(0, 0, Properties.Settings.Default.AutoSaveInterval);
            timer.Tick += new EventHandler(timer_Tick);

            //工作目录
            try
            {
                Directory.CreateDirectory(scriptsPath);
                Directory.CreateDirectory(newScriptsPath);
                Directory.CreateDirectory(savedTranslationsPath);
            }
            catch (Exception exception)
            {
                MessageBox.Show("无法创建脚本文件目录。\r\n" + exception.Message);
            }
        }

        void timer_Tick(object sender, EventArgs e)
        {
            if (!timer.IsEnabled)
                return;
            if (dataTable.Rows.Count == 0)
                return;

            SaveWorkWithFile(savedTranslationsPath + "\\" + Path.GetFileNameWithoutExtension(currentFilePath) + ".autosave");
            textBlockInfo.Text = "自动保存于 " + DateTime.Now;
        }

        private void listViewMain_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
        {
            //通常按下
            if (e.KeyboardDevice.Modifiers == ModifierKeys.None)
            {
                if (e.Key == Key.Up)
                {
                    e.Handled = true;
                    SelectListViewItem(listViewMain.SelectedIndex - 1);

                    //修正上翻时滚动到界外的BUG
                    listViewMain.ScrollIntoView(listViewMain.SelectedItem);
                }
                if (e.Key == Key.Down)
                {
                    e.Handled = true;
                    SelectListViewItem(listViewMain.SelectedIndex + 1);
                }
                if (e.Key == Key.Enter)
                {
                    e.Handled = true;
                    SelectListViewItem(listViewMain.SelectedIndex + 1);
                }
            }
            //CTRL
            if (e.KeyboardDevice.Modifiers == ModifierKeys.Control)
            {
                if (e.Key == Key.Enter)
                {
                    e.Handled = true;
                    if (library.GetCanMakeNewLine())
                    {
                        TextBox tb = GetElement(listViewMain.SelectedIndex, "textBoxNew");
                        tb.SelectedText = Environment.NewLine;
                        tb.SelectionLength = 0;
                        tb.SelectionStart += Environment.NewLine.Length;
                    }
                }
            }
        }

        private void listViewMain_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
        {
            if (listViewMain.SelectedIndex == -1)
                return;

            TextBox tb = GetElement(listViewMain.SelectedIndex, "textBoxNew");
            if (tb != null)//Begin here
            {
                e.Handled = true;
                tb.Focus();
            }
        }

        private void textBoxNew_GotFocus(object sender, RoutedEventArgs e)
        {
            TextBox textBox = (TextBox)sender;

            ListViewItem templateParent = FrameworkSupport.GetFrameworkParentByName<ListViewItem>(textBox);
            if (templateParent != null)
            {
                listViewMain.SelectedItems.Clear();
                templateParent.IsSelected = true;
            }

            //选定文本
            int[] i = Support.Backend.TextSupport.SelectTextBox(textBox.Text);

            textBox.SelectionStart = i[0];

            textBox.SelectionLength = i[1];
        }

        private void menuViewSettings_Click(object sender, RoutedEventArgs e)
        {
            WindowSetting ws = new WindowSetting(this);
            ws.ShowDialog();
        }

        private void formMain_Loaded(object sender, RoutedEventArgs e)
        {
            Title = "Script Text Editor 2.5 Beta 1 - " + library.GetLibraryInfo();

            dataTable.Columns.Add("OrgText", typeof(string));
            dataTable.Columns.Add("NewText", typeof(string));
            dataTable.Columns.Add("Marked", typeof(bool));

            listViewMain.ItemsSource = dataTable.DefaultView;
        }

        private void formMain_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            if (isTextChanged)
                if (MessageBox.Show("修改未保存，确定退出吗？", "注意", MessageBoxButton.YesNo) == MessageBoxResult.No)
                {
                    e.Cancel = true;
                    return;
                }
            Environment.Exit(0);
        }

        private void buttonSearchPanel_Click(object sender, RoutedEventArgs e)
        {
            if (dataTable.Rows.Count == 0)
                return;

            if (searchPanel.Visibility == Visibility.Collapsed)
                searchPanel.Visibility = Visibility.Visible;
            else
                searchPanel.Visibility = Visibility.Collapsed;
        }

        private void buttonMark_Click(object sender, RoutedEventArgs e)
        {
            if (dataTable.Rows.Count == 0)
                return;

            if (listViewMain.SelectedIndex == -1)
                return;

            dataTable.Rows[listViewMain.SelectedIndex]["Marked"] = true;
        }

        private void buttonMarkPrev_Click(object sender, RoutedEventArgs e)
        {
            if (dataTable.Rows.Count == 0)
                return;

            for (int i = listViewMain.SelectedIndex - 1; i > -1; i--)
            {
                if ((bool)dataTable.Rows[i]["Marked"])
                {
                    listViewMain.SelectedIndex = i;
                    break;
                }
            }
        }

        private void buttonMarkNext_Click(object sender, RoutedEventArgs e)
        {
            if (dataTable.Rows.Count == 0)
                return;

            for (int i = listViewMain.SelectedIndex + 1; i < listViewMain.Items.Count; i++)
            {
                if ((bool)dataTable.Rows[i]["Marked"])
                {
                    listViewMain.SelectedIndex = i;
                    break;
                }
            }
        }

        private void buttonMarkErase_Click(object sender, RoutedEventArgs e)
        {
            if (dataTable.Rows.Count == 0)
                return;

            dataTable.Rows[listViewMain.SelectedIndex]["Marked"] = false;
        }

        private void buttonMarkEraseAll_Click(object sender, RoutedEventArgs e)
        {
            if (dataTable.Rows.Count == 0)
                return;

            for (int i = 0; i < dataTable.Rows.Count; i++)
                if ((bool)dataTable.Rows[i]["Marked"])
                {
                    dataTable.Rows[i]["Marked"] = false;
                }
        }

        private void buttonSearchPanelNext_Click(object sender, RoutedEventArgs e)
        {
            int result = FindTextInDataTable(textBoxSearchPanelOrg.Text, listViewMain.SelectedIndex + 1, 1, comboBoxSearchPanelOption.SelectedIndex);
            listViewMain.SelectedIndex = result;

            BringCurrentItemIntoView();
        }

        private void buttonSearchPanelPrev_Click(object sender, RoutedEventArgs e)
        {
            int result = FindTextInDataTable(textBoxSearchPanelOrg.Text, listViewMain.SelectedIndex - 1, -1, comboBoxSearchPanelOption.SelectedIndex);
            listViewMain.SelectedIndex = result;

            listViewMain.ScrollIntoView(listViewMain.SelectedItem);
        }

        private void buttonSearchPanelReplace_Click(object sender, RoutedEventArgs e)
        {
            int result = FindTextInDataTable(textBoxSearchPanelOrg.Text, listViewMain.SelectedIndex, 1, 2);//，从当前行开始，只查找译文

            if (result == -1) return;

            dataTable.Rows[result]["NewText"] =
                ((string)dataTable.Rows[result]["NewText"]).Replace(
                textBoxSearchPanelOrg.Text,
                textBoxSearchPanelNew.Text
                );

            listViewMain.SelectedIndex = result;

            listViewMain.ScrollIntoView(listViewMain.SelectedItem);
        }

        private void buttonSearchPanelReplaceAll_Click(object sender, RoutedEventArgs e)
        {
            if (dataTable.Rows.Count == 0)
                return;

            for (int i = 0; i < dataTable.Rows.Count; i++)
            {
                dataTable.Rows[i]["NewText"] =
                    ((string)dataTable.Rows[i]["NewText"]).Replace(
                    textBoxSearchPanelOrg.Text,
                    textBoxSearchPanelNew.Text
                    );
            }

            textBlockInfo.Text = "替换完成。";
        }

        void dataTable_RowChanged(object sender, DataRowChangeEventArgs e)
        {
            isTextChanged = true;
        }

        private void menuFileNew_Click(object sender, RoutedEventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = library.GetSupportExtensions();
            ofd.InitialDirectory = scriptsPath;
            if (ofd.ShowDialog() == true)
            {
                BeginWorkWithFile(ofd.FileName);

                //Add event
                dataTable.RowChanged += new DataRowChangeEventHandler(dataTable_RowChanged);
            }
        }

        private void menuFileContinue_Click(object sender, RoutedEventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = "*.sav|*.sav";
            ofd.InitialDirectory = savedTranslationsPath;
            if (ofd.ShowDialog() == true)
            {
                ContinueWorkWithFile(ofd.FileName);

                //Add event
                dataTable.RowChanged += new DataRowChangeEventHandler(dataTable_RowChanged);
            }
        }

        private void menuFileSave_Click(object sender, RoutedEventArgs e)
        {
            SaveFileDialog sfd = new SaveFileDialog();
            sfd.Filter = "*.sav|*.sav";
            sfd.FileName = Path.GetFileNameWithoutExtension(currentFilePath);
            sfd.InitialDirectory = savedTranslationsPath;
            if (sfd.ShowDialog() == true)
            {
                SaveWorkWithFile(sfd.FileName);
            }
        }

        private void menuFileFinish_Click(object sender, RoutedEventArgs e)
        {
            SaveFileDialog sfd = new SaveFileDialog();
            sfd.Filter = library.GetSupportExtensions();
            sfd.FileName = Path.GetFileNameWithoutExtension(currentFilePath);
            sfd.InitialDirectory = newScriptsPath;
            if (sfd.ShowDialog() == true)
            {
                FinishWorkWithFile(sfd.FileName);
            }
        }

        private void menuExit_Click(object sender, RoutedEventArgs e)
        {
            this.Close();
        }

        private void nemuEditBatchOutput_Click(object sender, RoutedEventArgs e)
        {
        }
    }
}